package com.jz.digital.utils;

import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: lyw
 * @package: com.ido.veryfitpro.util;
 * @description: ${TODO}{ google gson 解析辅助类封装了gson解析字符串成对象和集合方法并且捕获了异常}
 * @date: 2018/5/30
 */
public class GsonUtil {
    /**
     * 解析集合
     *
     * @param json
     * @param clazz
     * @param typeClass
     * @param <T>
     * @return
     */
    public static <T> T fromJsonType(String json, final Class<T> clazz, final Class typeClass) {
        Gson gson = new Gson();
        final Type listType = new ParameterizedType() {
            public Type getRawType() {
                return List.class;
            }

            public Type[] getActualTypeArguments() {
                return new Type[]{typeClass};
            }

            public Type getOwnerType() {
                return null;
            }
        };
        Type objectType = new ParameterizedType() {
            public Type getRawType() {
                return clazz;
            }

            public Type[] getActualTypeArguments() {
                return new Type[]{listType};
            }

            public Type getOwnerType() {
                return null;
            }
        };
        return gson.fromJson(json, objectType);
    }

    /**
     * 把json转成List集合
     *
     * @param json
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> List<T> analysisJsonArrayToList(String json, Class<T[]> clazz) {
        if (TextUtils.isEmpty(json)) {
            return null;
        }
        Gson gson = new Gson();
        T[] array = null;
        try {
            array = gson.fromJson(json, clazz);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (array == null) {
            return null;
        }
        return Arrays.asList(array);
    }

    /**
     * 把json转成List集合
     *
     * @param json
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> List<T> analysisJsonObjectToList(String json, Class<T> clazz) {
        if (TextUtils.isEmpty(json)) {
            return null;
        }
        Gson gson = new Gson();
        Type type = new TypeToken<ArrayList<JsonObject>>() {
        }.getType();
        ArrayList<JsonObject> jsonObjects = gson.fromJson(json, type);
        if (jsonObjects == null) {
            return null;
        }
        ArrayList<T> arrayList = new ArrayList<T>();
        for (JsonObject jsonObject : jsonObjects) {
            arrayList.add(gson.fromJson(jsonObject, clazz));
        }
        return arrayList;
    }

    /**
     * 把对象转成json字符串
     * 若解析异常何返回null
     *
     * @param obj
     * @return
     */
    public static String toJson(Object obj) {
        Gson gson = new GsonBuilder().serializeSpecialFloatingPointValues()
                .create();
        try {
            return gson.toJson(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    public static JsonElement toJsonTree(Object obj) {
        Gson gson = new Gson();
        try {
            return gson.toJsonTree(obj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }


    /**
     * gson字符串转换为Map集合
     * 解析出错则返回Null
     *
     * @return Map
     */
    public static <K, V> Map<K, V> fromJson2Map(String jsonString) {
        Gson gson = new Gson();
        Map<K, V> result = null;
        try {
            result = gson.fromJson(jsonString, new TypeToken<HashMap<String, Object>>() {
            }.getType());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * jsonString 字符串转换为集合对象
     * 解析出错返回null
     *
     * @param jsonString json字符串
     * @return T 集合
     * @see {{@link #fromJson2Map(String)}}
     */
    @Deprecated
    public static <K, V> Map fromJsonToMap(String jsonString) {
        Map result = null;
        Gson gson = new Gson();
        try {
            result = gson.fromJson(jsonString, new TypeToken<Map<K, V>>() {
            }.getType());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * jsonString 字符串转换为集合对象
     * 解析出错返回null
     *
     * @param jsonString json字符串
     * @return T 集合
     */
    public static <T> T fromJsonToCollect(String jsonString) {
        T result = null;
        Gson gson = new Gson();
        try {
            result = gson.fromJson(jsonString, new TypeToken<T>() {
            }.getType());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }

    /**
     * @param gsonStr json字符串
     * @param clazz   返回的类型
     * @param <T>
     * @return 解析错误返回null
     */
    public static <T> T fromJson(String gsonStr, Class<T> clazz) {
        Gson gson = new Gson();
        try {
            return gson.fromJson(gsonStr, clazz);
        } catch (Exception e) {
            return null;
        }

    }

    public static <T> T fromJson(String gsonStr, Type type) {
        Gson gson = new Gson();
        try {
            return gson.fromJson(gsonStr, type);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * @param gsonStr json字符串
     * @param clazz   返回的类型
     * @param <T>
     * @return 解析错误返回null
     */
    public static <T> T fromJson(String gsonStr, Class<T> clazz, Class<?> typeClazz) {
        Gson gson = new Gson();
        try {
            Type objectType = type(clazz, typeClazz);
            return gson.fromJson(gsonStr, objectType);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    static ParameterizedType type(final Class raw, final Type... args) {
        return new ParameterizedType() {
            public Type getRawType() {
                return raw;
            }

            public Type[] getActualTypeArguments() {
                return args;
            }

            public Type getOwnerType() {
                return null;
            }
        };
    }

}
